#include"ThreadCache.h"
#include"CentralCache.h"
void* ThreadCache::Allocate(size_t size)
{
	assert(size <= Max_Bytes);
	size_t alignsize = sizeClass::RoundUp(size);//对齐后的数目
	size_t index = sizeClass::Index(size);//桶的下标
	//映射位置有空间可用
	if (!_freelist[index] .empty())
	{
		return  _freelist[index].Pop();
	}
	//没有就找中心cache
	else
	{
		return	FetchFromCentralCache(index,alignsize);
	}

}
void ThreadCache::Deallocate(void* ptr, size_t size)
{
	assert(ptr);
	assert(size<=Max_Bytes);
	size_t index = sizeClass::Index(size);
	_freelist[index].Push(ptr);
	//如果超过一定量,释放回中心缓存
	if (_freelist[index].Size() >= _freelist[index].Maxsize())
	{
		 ListTooLong(_freelist[index],size);
	}
}
void ThreadCache::ListTooLong(FreeList& list, size_t size)
{
	void* start = nullptr;
	void* end = nullptr;
	list.PopRange(start, end, list.Maxsize());
	CentralCache::GetInstance()->ReleaseListToSpans(start, size);
}
void* ThreadCache::FetchFromCentralCache(size_t index, size_t size)
{
	//慢开始算法
	//第一次要一个
	//size越大，最大上限就越小
	//size越小，最大上限就是越大512
	size_t batchnum = min(_freelist[index].Maxsize(), sizeClass::NumMoveSize(size));
	if (_freelist[index].Maxsize() == batchnum)
	{
		_freelist[index].Maxsize()+=1;
	}
	void* start = nullptr;
	void* end = nullptr;
	size_t actualnum = CentralCache::GetInstance()->FetchRangeObj(start, end, batchnum, size);//输出型参数
	assert(actualnum >0);
	if (actualnum == 1)
	{
		//只有头结点
		assert(start == end);
		return start;
	}
	else
	{
		_freelist[index].PushRange(Nextobj(start), end,actualnum-1);//包含头结点
		return start;
	}
	

}